package gatperdut.chato.lucene.indexer;

import gatperdut.chato.constants.CSConstantsLucene;
import gatperdut.chato.lucene.parser.CMParser;
import gatperdut.chato.lucene.parseresult.CMParseResult;

import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.xml.stream.XMLStreamException;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;

public abstract class CMIndexer {

    private final IndexWriter writer;

    private final FileFilter filter = new XMLFilesFilter();

    private CMParser parser;

    public CMIndexer( IndexWriter writer ) throws IOException {
        this.writer = writer;
    }

    public abstract String getDataPath();

    public abstract Document getDocument( File f ) throws IOException;

    public abstract CMParser getNewParser( File f ) throws FileNotFoundException, XMLStreamException;

    public int index() throws IOException, XMLStreamException {
        File[] files = new File( getDataPath() ).listFiles();

        for ( File f : files ) {
            if ( getFilter().accept( f ) ) {
                System.out.println( "Indexing " + f.getCanonicalPath() );
                setParser( getNewParser( f ) );
                getParser().parse();
                Document doc = getDocument( f );
                getWriter().addDocument( doc );
            }
        }

        return writer.numDocs();
    }

    public void fillDocumentCommonStuff( Document doc, CMParseResult parseResult ) {
        doc.add( new Field( CSConstantsLucene.FIELD_TITLE, parseResult.getTitle(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS ) );

        doc.add( new Field( CSConstantsLucene.FIELD_TOPIC, parseResult.getTopic(), Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS ) );

        doc.add( new Field( CSConstantsLucene.FIELD_CATCH_ALL, parseResult.getCatchAllString(), Field.Store.NO, Field.Index.ANALYZED ) );

        for ( String s : parseResult.getSeeAlso() ) {
            doc.add( new Field( CSConstantsLucene.FIELD_RELATED, s, Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS ) );
        }
    }

    public static class XMLFilesFilter implements FileFilter {
        public boolean accept( File f ) {
            if ( f.isDirectory() || f.isHidden() || !f.exists() || !f.canRead() ) {
                return false;
            }
            return f.getName().toLowerCase().endsWith( ".xml" );
        }
    }

    public static String[] getContentFieldsByDocType( String docType ) {
        if ( CSConstantsLucene.TOPIC_MECHANISM.equals( docType ) ) {
            return new String[] { CSConstantsLucene.FIELD_DESCRIPTION };
        }
        if ( CSConstantsLucene.TOPIC_COMMAND.equals( docType ) ) {
            return new String[] { CSConstantsLucene.FIELD_USAGE };
        }

        return null;
    }

    public CMParser getParser() {
        return parser;
    }

    public void setParser( CMParser parser ) {
        this.parser = parser;
    }

    public IndexWriter getWriter() {
        return writer;
    }

    public FileFilter getFilter() {
        return filter;
    }
}
